package org.demo.client;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.internal.bind.TypeAdapters;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import retrofit2.Retrofit;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.security.SecureRandom;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 作者：lizw <br/>
 * 创建时间：2017/10/18 17:20 <br/>
 */
@Slf4j
public class ClientFactory {

    private static final OkHttpClient OK_HTTP_CLIENT;
    private static final Gson GSON;

    static {
        long timeout = 60L;
        TrustAllManager trustAllManager = new TrustAllManager();
        OK_HTTP_CLIENT = new OkHttpClient.Builder()
                .addInterceptor(chain -> {
                    Request request = chain.request().newBuilder()
                            .addHeader("Accept-Language", "zh-CN,zh;q=0.8")
                            .build();
                    long start = System.currentTimeMillis();
                    log.info(String.format("---> 请求 [%1$s] %2$s ", request.method(), request.url()));
                    Response response = chain.proceed(request);
                    long end = System.currentTimeMillis();
                    log.info(String.format("<--- 响应 [%1$d] %2$s (%3$dms)", response.code(), response.request().url(), (end - start)));
                    return response;
                })
                .readTimeout(timeout, TimeUnit.SECONDS)
                .connectTimeout(timeout, TimeUnit.SECONDS)
                .sslSocketFactory(createTrustAllSSLFactory(trustAllManager), trustAllManager)
                .hostnameVerifier(new TrustAllHostnameVerifier())
                .build();

        GSON = new GsonBuilder()
                .serializeNulls()
                .setDateFormat("yyyy-MM-dd HH:mm:ss")
                .registerTypeAdapterFactory(TypeAdapters.newFactory(Date.class, new DateTypeAdapter(Date.class)))
                .create();
    }

    private static SSLSocketFactory createTrustAllSSLFactory(TrustAllManager trustAllManager) {
        SSLSocketFactory ssfFactory = null;
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, new TrustManager[]{trustAllManager}, new SecureRandom());
            ssfFactory = sc.getSocketFactory();
        } catch (Exception e) {
            log.warn("SSLSocketFactory init ", e);
        }
        return ssfFactory;
    }

    /**
     * 获取客户端代理
     *
     * @param baseUrl 请求地址
     * @param clazz   客户端接口类
     * @param <T>     客户端类型
     * @return 客户端代理
     */
    public static <T> T getClient(String baseUrl, Class<T> clazz) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(OK_HTTP_CLIENT)
                .addConverterFactory(CustomGsonConverterFactory.create(GSON))
                .build();
        return retrofit.create(clazz);
    }
}

